Skip to content

fix: add tree hash and patch ID checkpoint linkage fallback#840

Open
peyton-alt wants to merge 21 commits intomainfrom
peyton/ent-834-tree-hash-checkpoint-linkage
Open

fix: add tree hash and patch ID checkpoint linkage fallback#840
peyton-alt wants to merge 21 commits intomainfrom
peyton/ent-834-tree-hash-checkpoint-linkage

Conversation

@peyton-alt
Copy link
Copy Markdown
Contributor

@peyton-alt peyton-alt commented Apr 3, 2026

Summary

Store a narrow, Git-native linkage block in checkpoint metadata so the web has limited fallback signals when history rewrites strip the Entire-Checkpoint trailer.

  • add checkpoint-level linkage metadata with tree_hash and patch_id
  • keep the existing active-session revert/cherry-pick trailer behavior, but only reuse an existing LastCheckpointID
  • avoid generating new checkpoint IDs during sequence operations, since those commits are not condensed immediately

Scope

This PR is intentionally narrow.

It does not implement full automatic relinking across all rewrite scenarios, and it does not add custom derived signals like files_changed_hash or session_files_hash.

The supported fallback signals are:

  • tree_hash for message-only rewrites where the tree is unchanged
  • patch_id for clean rebases or cherry-picks where the diff content is unchanged

Why this shape

The broader multi-signal design implied server-side indexing and reconciliation work that this PR does not provide.

This branch keeps only the cheap, Git-native fallback signals that are defensible today, while the real active-session rewrite tracking work moves to the CLI (post-rewrite) in a separate follow-up.

Sequence-operation behavior

prepare-commit-msg can still add a trailer during agent-driven revert/cherry-pick when a session is ACTIVE, but it now only reuses an existing LastCheckpointID.

That matters because post-commit still skips condensation while the sequence operation is in progress. Reusing an existing checkpoint ID preserves a valid link; minting a fresh one would leave a dangling Entire-Checkpoint trailer on the commit.

Testing

Passed:

  • GOCACHE=/tmp/go-build go test ./cmd/entire/cli/strategy -run 'TestShadowStrategy_(PrepareCommitMsg_(AgentRevertReusesLastCheckpointID|AgentRevertWithoutCheckpointIDSkipped|UserRevertSkipped)|PostCommit_LinkagePopulated)' -count=1
  • GOCACHE=/tmp/go-build go test ./cmd/entire/cli/checkpoint ./cmd/entire/cli/gitops -count=1
  • GOCACHE=/tmp/go-build GOLANGCI_LINT_CACHE=/tmp/golangci-lint golangci-lint run ./cmd/entire/cli/strategy ./cmd/entire/cli/checkpoint ./cmd/entire/cli/gitops

Included coverage verifies:

  • linkage is written at the checkpoint summary level
  • both tree_hash and patch_id are populated in the condensation path
  • clean rebases keep a stable patch_id
  • agent-driven revert reuses an existing checkpoint trailer when available
  • agent-driven revert skips trailer injection when no existing checkpoint ID can be reused
  • user-driven revert still skips trailer injection

Copilot AI review requested due to automatic review settings April 3, 2026 00:25
@peyton-alt peyton-alt requested a review from a team as a code owner April 3, 2026 00:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Stores a commit’s git tree hash in checkpoint metadata during condensation so the web side can re-link checkpoints after history rewrites that drop the Entire-Checkpoint trailer, and tweaks prepare-commit-msg behavior so agent-driven revert/cherry-pick operations still get checkpoint trailers when a session is active.

Changes:

  • Add tree_hash to committed checkpoint metadata (CommittedMetadata, WriteCommittedOptions) and populate it during PostCommit condensation from the HEAD commit’s tree hash.
  • Allow prepare-commit-msg to proceed during git sequence operations (revert/cherry-pick/rebase) when an ACTIVE session exists in the current worktree; keep skipping when no active session.
  • Add unit tests for tree_hash persistence and the new revert trailer behavior split by agent-active vs user/manual.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
cmd/entire/cli/strategy/manual_commit_test.go Adds tests ensuring agent revert gets a trailer when session is ACTIVE and user revert is skipped when not active.
cmd/entire/cli/strategy/manual_commit_session.go Adds helper to detect whether any session in the current worktree is ACTIVE.
cmd/entire/cli/strategy/manual_commit_hooks.go Adjusts PrepareCommitMsg sequence-operation skip logic; passes commit tree hash into condensation options.
cmd/entire/cli/strategy/manual_commit_condensation.go Threads treeHash through condensation options into committed checkpoint write options.
cmd/entire/cli/checkpoint/committed.go Writes TreeHash into per-session committed metadata.json.
cmd/entire/cli/checkpoint/checkpoint.go Extends checkpoint option/metadata structs to include TreeHash serialized as tree_hash.
cmd/entire/cli/checkpoint/checkpoint_test.go Adds coverage that tree_hash is written and read back from committed metadata.

Comment thread cmd/entire/cli/strategy/manual_commit_test.go
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Comment thread cmd/entire/cli/strategy/manual_commit_hooks.go Outdated
peyton-alt added a commit that referenced this pull request Apr 3, 2026
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pjbgf added a commit that referenced this pull request Apr 3, 2026
Add checkpoint linkage preservation after history rewrites (#840) and
fail-closed content detection in prepare-commit-msg (#826). Update
release date to 2026-04-03.

Signed-off-by: Paulo Gomes <paulo@entire.io>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 0154164ac0f9
pjbgf added a commit that referenced this pull request Apr 3, 2026
Add checkpoint linkage preservation after history rewrites (#840) and
fail-closed content detection in prepare-commit-msg (#826). Update
release date to 2026-04-03.

Signed-off-by: Paulo Gomes <paulo@entire.io>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 0154164ac0f9
pjbgf added a commit that referenced this pull request Apr 3, 2026
Add checkpoint linkage preservation after history rewrites (#840) and
fail-closed content detection in prepare-commit-msg (#826). Update
release date to 2026-04-03.

Signed-off-by: Paulo Gomes <paulo@entire.io>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 0154164ac0f9
@peyton-alt peyton-alt marked this pull request as draft April 7, 2026 05:49
@peyton-alt peyton-alt force-pushed the peyton/ent-834-tree-hash-checkpoint-linkage branch from 7b9d87d to 8302847 Compare April 7, 2026 06:17
@peyton-alt peyton-alt changed the title fix: store tree hash in checkpoint metadata for linkage resilience feat: multi-signal checkpoint linkage for resilience across git rewrites Apr 7, 2026
@peyton-alt peyton-alt force-pushed the peyton/ent-834-tree-hash-checkpoint-linkage branch 3 times, most recently from 0dfcba0 to 703bd67 Compare April 7, 2026 23:55
@peyton-alt peyton-alt marked this pull request as ready for review April 8, 2026 00:17
@peyton-alt peyton-alt force-pushed the peyton/ent-834-tree-hash-checkpoint-linkage branch from 703bd67 to fa8cbb5 Compare April 10, 2026 01:34
@peyton-alt peyton-alt changed the title feat: multi-signal checkpoint linkage for resilience across git rewrites fix: checkpoint linkage survives git rebase and history rewrites Apr 10, 2026
peyton-alt and others added 9 commits April 9, 2026 22:08
When an agent runs git revert or cherry-pick as part of its work, the
commit should be checkpointed. Previously prepare-commit-msg
unconditionally skipped during sequence operations, making the agent's
work invisible to Entire.

Now checks for active sessions: if an agent session is ACTIVE, the
operation is agent-initiated and gets a trailer. If no active session,
it's user-initiated and is skipped as before.

Part of fix for #834.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 85df9ac94bc7
Add tree_hash field to committed checkpoint metadata. Records the git
tree hash of the commit being condensed, enabling fallback checkpoint
lookup by tree hash when the Entire-Checkpoint trailer is stripped by
git history rewrites (rebase, filter-branch, amend).

Part of fix for #834.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 77773a25069e
- Add debug logging to hasActiveSessionInWorktree error paths
- Remove unrelated files (greetings.md, agent configs) from PR

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: bacd9b68b1c0
Define content-based linkage signals (tree_hash, patch_id,
files_changed_hash, session_files_hash) for re-linking checkpoints
after git history rewrites. Stored at checkpoint level, not per-session.

Part of fix for #834.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 4661e8c50610
Needed by linkage signal tests that verify patch ID stability across rebase.

Part of fix for #834.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 4129c08c80b0
ComputePatchID: git patch-id of the commit diff, survives rebase.
ComputeFilesChangedHash: SHA256 of sorted file:blob pairs, survives
rebase even with conflicts in non-agent files. Uses single git ls-tree
call for all files (O(1) subprocess).

Part of fix for #834.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: c100b592e3a0
Replace per-session TreeHash with checkpoint-level LinkageMetadata
containing tree_hash, patch_id, files_changed_hash, and session_files_hash.
Computed in PostCommit handlers, passed through condenseOpts to
CondenseSession, written to CheckpointSummary on entire/checkpoints/v1.

Part of fix for #834.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 75ce05cfe11b
Verify LinkageMetadata is stored in CheckpointSummary and readable.
Also verify nil linkage is omitted (backward compat with old checkpoints).

Part of fix for #834.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 10dae87903d7
gofmt stripped nolint directives from capabilities.go. Restore from main.
Add encoding/hex import for ComputeFilesChangedHash.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: c26d3dce1d32
peyton-alt and others added 3 commits April 9, 2026 22:08
- Restore nolint:ireturn on capabilities.go (gofmt stripped them)
- Set user.name/email in gitops initTestRepo for CI compatibility
  (git rebase fails without repo-level config on CI runners)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f1ca53b63c79
- Add omitempty to all LinkageMetadata JSON tags for consistency
- Return error for malformed git ls-tree lines instead of silent skip
- Compute commit-level linkage once (not per-session) via baseLinkage
  cache; only SessionFilesHash varies per session
- Add code comment explaining deferred condensation for agent reverts
- Add integration test verifying full linkage pipeline (PostCommit →
  condensation → ReadCommitted with all four signals populated)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: e3539c5bfa31
- Replace unreachable Fields/len guard with strings.Cut in ComputePatchID
- Use logCtx variable in linkageForSession for logging consistency
- Use strings.TrimSpace in revParse test helper instead of raw byte slice

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 91b06c4aabdb
@peyton-alt peyton-alt force-pushed the peyton/ent-834-tree-hash-checkpoint-linkage branch from fa8cbb5 to 7cfa919 Compare April 10, 2026 05:09
@peyton-alt peyton-alt changed the title fix: checkpoint linkage survives git rebase and history rewrites fix: add tree hash and patch ID checkpoint linkage fallback Apr 15, 2026
@peyton-alt peyton-alt force-pushed the peyton/ent-834-tree-hash-checkpoint-linkage branch from 7487fcf to da5cea2 Compare April 15, 2026 05:30
Copy link
Copy Markdown
Collaborator

@Soph Soph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Review Suggestions:

  1. Misleading field name IsRebaseInProgress at cmd/entire/cli/strategy/manual_commit_hooks.go:1098 — now also covers cherry-pick and revert. Rename to IsSequenceOperationInProgress or add a comment.
  2. PatchID unstable under conflict-resolved rebasesgit patch-id --stable changes if the user resolves conflicts during rebase. Add a one-line doc note on PatchID in LinkageMetadata.
  3. Missing cherry-pick test for PrepareCommitMsg with an active session (revert is covered thoroughly, cherry-pick is symmetric).
  4. Duplicate helpers in cmd/entire/cli/gitops/diff_test.go (revParse, gitCheckout, gitRebase) shadow the new testutil helpers added in this branch — maybe replace them?
  5. Document "same ID from two sessions = ambiguous" in singleReusableCheckpointID — the behavior is correct, just non-obvious.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants